/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.championship;

import br.com.controllers.Controller;
import br.com.models.ClassRoom;
import br.com.models.Days;
import br.com.models.Discipline;
import br.com.models.Teacher;
import java.util.ArrayList;
import java.util.LinkedList;

/**
 *
 * @author Valdigleis
 */
public class ChampionShip {
    
    private Controller controller;
    
    private ArrayList<ClassRoom> classRoom;
    
    private LinkedList<Gamer> gamers;
    
    private LinkedList<Gamer> players;
    
    private LinkedList<Gamer> winners;
    
    private String semesterWon;
    
    private ResultDay resultDay;
    
    private int aux;
    
    private int k;
    
    public ChampionShip(String semester) {
        this.controller = new Controller();
        this.classRoom = this.controller.getAllClassRoom(semester);
        this.gamers = new LinkedList<Gamer>();
        this.winners = new LinkedList<Gamer>();
        this.players = new LinkedList<Gamer>();
        this.resultDay = new ResultDay();
        this.semesterWon = semester;
        this.k = 10;
    }
    
    public void run(int period){
            this.aux = period;
            getGamers(period);
            this.k = 0;
            for(int i = 1; i < 6 ; i++){
                for(int j = 1; j < 3 ; j++){
                    competiton(i, j);
                    this.k++;
               }
           }
    }
    
    private void removerByPeriod(int p){
        for(int i = 0; i < this.players.size(); i++){
            if(this.players.get(i).getClassRoom().getDiscipline().getSemester() == p){
                this.players.remove(i);
            }
        }
    }
    
    private void competiton(int day, int alfa){
        removerByLocade();
        getPlayers();
        if(this.winners.size() > 0){
            removerByVictory();
            this.winners.clear();
        }
        removerByDay(day);
        removerByPos(day);
        if(this.aux > 1){
            removerByPeriod((this.aux - 1));
        }
        removerByTeacher();
        updateAtt();
        if(this.players.size() > 1){
            rodade();
            setVictorius();
            int i = localizeGamer(this.winners.get(0));
            if(i >= 0){
                updateLocade(this.gamers.get(i));
                this.resultDay.inster(this.aux, this.winners.get(0).getClassRoom());
            }else{
                this.resultDay.inster(this.aux, this.winners.get(0).getClassRoom());
            }
        }else{
            if(this.players.size() == 1){
                this.winners.add(this.players.get(0));
                int i = localizeGamer(this.winners.get(0));
                if(i >= 0){
                    updateLocade(this.gamers.get(i));
                }
            this.resultDay.inster(this.aux, this.winners.get(0).getClassRoom());
            }else{
                this.resultDay.inster(this.aux, setResultInvalido());
            }
        }
    }
    
    // pega as disciplinas do semestre.
    private void getGamers(int semester){
        for(int  i = 0; i < this.classRoom.size(); i++){
            if(this.classRoom.get(i).getDiscipline().getSemester() == semester){
                Gamer gamer = new Gamer();
                gamer.setClassRoom(this.classRoom.get(i));
                gamer.setLocado(0);
                gamer.setVictory(0);
                this.gamers.add(gamer);
            }
        }
    }
    
    // pega todos os jogadores para a rodada.
    private void getPlayers(){
        this.players.clear();
        for(int i = 0; i < this.gamers.size(); i++){
            Gamer gamer = new Gamer();
            gamer.setClassRoom(this.gamers.get(i).getClassRoom());
            gamer.setLocado(this.gamers.get(i).getLocado());
            gamer.setVictory(0);
            this.players.add(gamer);
        }
    }

    // executa o campeonato
    private void rodade(){
        for(int i = 0; i < this.players.size(); i++){
            for(int j = i+1; j < this.players.size(); j++){
                Game game = new Game();
                game.game1(this.players.get(i), this.players.get(j));
                game.game2(this.players.get(i), this.players.get(j));
                game.game3(this.players.get(i), this.players.get(j));
                game.game4(this.players.get(i), this.players.get(j));
            }
        }
    }
    
    //Remove as disciplinas que não possuem o dia atual.
    private void removerByDay(int day){
        Days days = this.controller.getDay(day);
        int err;
        for(int i = 0; i < this.players.size(); i++){
            err = 1;
            for(int j = 0; j < this.players.get(i).getClassRoom().getTeacher().getDays().size(); j++){
                if(this.players.get(i).getClassRoom().getTeacher().getDays().get(j).getId() == days.getId()){
                    
                    err = 0;
                }
            }
            if(err == 1){
                this.players.remove(i);
            }
        }
    }

    //Remove as disciplinas que os pos requisitos não pode ter aula nesse dia.
    private void removerByPos(int day){
        for(int i = 0; i < this.players.size(); i++){
            int err = 0;
            for(int j = 0; j < this.classRoom.size(); j++){
                if(checkPos(this.classRoom.get(j).getDiscipline(), this.players.get(i).getClassRoom().getDiscipline())){
                    if(checkDay(this.classRoom.get(j).getTeacher(), day)){
                        err = 0;
                    }else{
                        err = 1;
                    }
                }
            }
            if(err == 1){
                this.players.remove(i);
            }
        }
    }
    
    //Remove aqueles cuja locação maxima já foi atingida.
    private void removerByLocade(){
        for(int i =0; i < this.gamers.size(); i++){
            int x = this.gamers.get(i).getLocado();
            int y = this.gamers.get(i).getClassRoom().getDiscipline().getCredits();
            if(x == y){
                this.gamers.remove(i);
            }
        }
    }
    
    //Remover Aqueles que estão na lista de vitoriosos
    private void removerByVictory(){
        for(int i = 0; i < this.players.size(); i++){
            int err = 0;
            for(int j = 0; j < this.winners.size(); j++){
                if(this.players.get(i).getClassRoom().getDiscipline().getId() == this.winners.get(j).getClassRoom().getDiscipline().getId()){
                    err = 1;
                }
            }
            if(err == 1){
                this.players.remove(i);
            }
        }
    }
    
    private void removerByTeacher(){
        for(int j = 0; j < this.players.size(); j++){
           for(int i = 1; i < this.aux; i++){
                if(this.resultDay.checkTeacher((this.aux - 1), this.k, this.players.get(j).getClassRoom().getTeacher())){
                    this.players.remove(j);
                }
            } 
        }
    }
    
    // Checa se uma disciplina é pós requisito da outra.
    private boolean checkPos(Discipline pos, Discipline pre){
        for(int  i = 0; i < pos.getPreRequisite().size(); i++){
            if(pos.getPreRequisite().get(i).getId() == pre.getId()){
                return true;
            }
        }
        return false;
    }
    
    // Checa se um professor tem um dia qualquer "i" no expediente.
    private boolean checkDay(Teacher teacher, int idDay){
        for(int  i = 0; i < teacher.getDays().size(); i++){
            if(teacher.getDays().get(i).getId() == idDay){
                return true;
            }
        }
        return false;
    }

    private void updateAtt(){
        for(int i = 0; i < this.players.size(); i++){
            int pos = this.controller.getIdAllPosRequisitos(this.players.get(i).getClassRoom().getDiscipline().getId()).size();
            this.players.get(i).updateAttributs(this.players.get(i).getClassRoom().getTeacher().getDays().size(), (10 - this.k), pos);
        }
    }
    
    private void setVictorius(){
        int max = 0;
        for(int i = 0; i < this.players.size(); i++){
            if(this.players.get(i).getVictory() > max){
                max = this.players.get(i).getVictory();
            }
        }
        for(int i = 0; i < this.players.size(); i++){
            if(this.players.get(i).getVictory() == max){
                    Gamer gamer = new Gamer();
                    gamer.setClassRoom(this.players.get(i).getClassRoom());
                    gamer.setLocado(this.players.get(i).getLocado());
                    gamer.setVictory(this.players.get(i).getVictory());
                    this.winners.add(gamer);
            }
        }
    }
    
    private int localizeGamer(Gamer gamer){
        for(int i = 0; i < this.gamers.size(); i++){
            if(gamer.getClassRoom().getDiscipline().getId() == this.gamers.get(i).getClassRoom().getDiscipline().getId()){
                return i;
            }
        }
        return -1;
    }
    
    private void updateLocade(Gamer gamer){
        gamer.setLocado(gamer.getLocado()+2);
    }
    
    public ResultDay getResultDay(){
        return this.resultDay;
    }

    private ClassRoom setResultInvalido(){
        ClassRoom indefinide = new ClassRoom();
        Discipline diver = new Discipline();
        diver.setId(99999);
        diver.setName("Não alocado!");
        indefinide.setDiscipline(diver);
        Teacher teacher = new Teacher();
        teacher.setId(99999);
        teacher.setName("Não alocado!");
        indefinide.setTeacher(teacher);
        return indefinide;
    }
}
